/*
    SUSAN® - Sole of Unix Save ANything

      Copyright (C) 2011-2016 Skyatlas Co. LTD

   

   
*/
/*
 * Kern Sibbald, Feb MM
 */
/**
 * @file
 * Director specific configuration and defines
 */
#ifndef BAREOS_DIRD_DIRD_CONF_H_
#define BAREOS_DIRD_DIRD_CONF_H_

#include "dird/client_connection_handshake_mode.h"
#include "dird/date_time_bitfield.h"
#include "lib/alist.h"
#include "lib/messages_resource.h"
#include "lib/resource_item.h"
#include "lib/tls_conf.h"

class dlist;
class json_t;

namespace directordaemon {

static std::string default_config_filename("bareos-dir.conf");

/**
 * Resource codes -- they must be sequential for indexing
 */
enum
{
  R_DIRECTOR = 1001,
  R_CLIENT,
  R_JOBDEFS,
  R_JOB,
  R_STORAGE,
  R_CATALOG,
  R_SCHEDULE,
  R_FILESET,
  R_POOL,
  R_MSGS,
  R_COUNTER,
  R_PROFILE,
  R_CONSOLE,
  R_DEVICE,
  R_USER,
  R_FIRST = R_DIRECTOR,
  R_LAST = R_USER /* keep this updated */
};

/**
 * Some resource attributes
 */
enum
{
  R_NAME = 1020,
  R_ADDRESS,
  R_PASSWORD,
  R_TYPE,
  R_BACKUP
};

/**
 * Job Level keyword structure
 */
struct s_jl {
  const char* level_name; /* level keyword */
  uint32_t level;         /* level */
  int32_t job_type;       /* JobType permitting this level */
};

/**
 * Job Type keyword structure
 */
struct s_jt {
  const char* type_name;
  uint32_t job_type;
};

/**
 * Definition of the contents of each Resource
 * Needed for forward references
 */
class ScheduleResource;
class ClientResource;
class FilesetResource;
class PoolResource;
class RunResource;
class DeviceResource;

/*
 * Print configuration file schema in json format
 */
bool PrintConfigSchemaJson(PoolMem& buff);

/*
 *   Director Resource
 */
class DirectorResource
    : public BareosResource
    , public TlsResource {
 public:
  DirectorResource() = default;
  virtual ~DirectorResource() = default;

  dlist* DIRaddrs = nullptr;
  dlist* DIRsrc_addr = nullptr;      /* Address to source connections from */
  char* query_file = nullptr;        /* SQL query file */
  char* working_directory = nullptr; /* WorkingDirectory */
  char* scripts_directory = nullptr; /* ScriptsDirectory */
  char* plugin_directory = nullptr;  /* Plugin Directory */
  alist* plugin_names = nullptr;     /* Plugin names to load */
  char* pid_directory = nullptr;     /* PidDirectory */
  char* subsys_directory = nullptr;  /* SubsysDirectory */
  std::vector<std::string> backend_directories;
  MessagesResource* messages = nullptr; /* Daemon message handler */
  uint32_t MaxConcurrentJobs = 0; /* Max concurrent jobs for whole director */
  uint32_t MaxConnections = 0;    /* Max concurrent connections */
  uint32_t MaxConsoleConnections = 0; /* Max concurrent console connections */
  utime_t FDConnectTimeout = {0};     /* Timeout for connect in seconds */
  utime_t SDConnectTimeout = {0};     /* Timeout for connect in seconds */
  utime_t heartbeat_interval = {0};   /* Interval to send heartbeats */
  utime_t stats_retention = {0};   /* Statistics retention period in seconds */
  bool optimize_for_size = false;  /* Optimize daemon for minimum memory size */
  bool optimize_for_speed = false; /* Optimize daemon for speed which may need
                              more memory */
  bool omit_defaults = false; /* Omit config variables with default values when
                         dumping the config */
  bool ndmp_snooping = false; /* NDMP Protocol specific snooping enabled */
  bool auditing = false;      /* Auditing enabled */
  alist* audit_events = nullptr;   /* Specific audit events to enable */
  uint32_t ndmp_loglevel = 0;      /* NDMP Protocol specific loglevel to use */
  uint32_t subscriptions = 0;      /* Number of subscribtions available */
  uint32_t subscriptions_used = 0; /* Number of subscribtions used */
  uint32_t jcr_watchdog_time = 0;  /* Absolute time after which a Job gets
                                  terminated  regardless of its progress */
  uint32_t stats_collect_interval =
      0;                 /* Statistics collect interval in seconds */
  char* verid = nullptr; /* Custom Id to print in version command */
  char* secure_erase_cmdline = nullptr; /* Cmdline to execute to perform secure
                                 erase of file */
  char* log_timestamp_format = nullptr; /* Timestamp format to use in generic
                                 logging messages */
  s_password keyencrkey;                /* Key Encryption Key */
};

/*
 * Device Resource
 *
 * This resource is a bit different from the other resources
 * because it is not defined in the Director
 * by Device { ... }, but rather by a "reference" such as
 * Device = xxx; Then when the Director connects to the
 * SD, it requests the information about the device.
 */
class DeviceResource : public BareosResource {
 public:
  DeviceResource() = default;
  virtual ~DeviceResource() = default;

  bool found = false;       /**< found with SD */
  int32_t num_writers = 0;  /**< number of writers */
  int32_t max_writers = 0;  /**< = 1 for files */
  int32_t reserved = 0;     /**< number of reserves */
  int32_t num_drives = 0;   /**< for autochanger */
  bool autochanger = false; /**< set if device is autochanger */
  bool open = false;        /**< drive open */
  bool append = false;      /**< in append mode */
  bool read = false;        /**< in read mode */
  bool labeled = false;     /**< Volume name valid */
  bool offline = false;     /**< not available */
  bool autoselect = false;  /**< can be selected via autochanger */
  uint32_t PoolId = 0;
  char ChangerName[MAX_NAME_LENGTH] = {0};
  char VolumeName[MAX_NAME_LENGTH] = {0};
  char MediaType[MAX_NAME_LENGTH] = {0};
};

/**
 * Console ACL positions
 */
enum
{
  Job_ACL = 0,
  Client_ACL,
  Storage_ACL,
  Schedule_ACL,
  Pool_ACL,
  Command_ACL,
  FileSet_ACL,
  Catalog_ACL,
  Where_ACL,
  PluginOptions_ACL,
  Num_ACL /**< keep last */
};

/**
 * Profile Resource
 */
class ProfileResource : public BareosResource {
 public:
  ProfileResource() = default;
  virtual ~ProfileResource() = default;

  alist* ACL_lists[Num_ACL] = {0}; /**< Pointers to ACLs */
};

struct UserAcl {
  BareosResource* corresponding_resource = nullptr;
  alist* ACL_lists[Num_ACL] = {0}; /**< Pointers to ACLs */
  alist* profiles = nullptr;       /**< Pointers to profile resources */
};

/**
 * Console Resource
 */
class ConsoleResource
    : public BareosResource
    , public TlsResource {
 public:
  ConsoleResource() = default;
  virtual ~ConsoleResource() = default;
  UserAcl user_acl;
  bool use_pam_authentication_ = false; /**< PAM Console */
};

class UserResource : public BareosResource {
 public:
  UserResource() = default;
  virtual ~UserResource() = default;
  UserAcl user_acl;
};

/**
 * Catalog Resource
 */
class CatalogResource : public BareosResource {
 public:
  CatalogResource() = default;
  virtual ~CatalogResource() = default;
  virtual bool Validate() override;

  uint32_t db_port = 0;       /**< Port */
  char* db_address = nullptr; /**< Hostname for remote access */
  char* db_socket = nullptr;  /**< Socket for local access */
  s_password db_password;
  char* db_user = nullptr;
  char* db_name = nullptr;
  char* db_driver = nullptr;        /**< Select appropriate driver */
  uint32_t mult_db_connections = 0; /**< Set if multiple connections wanted */
  bool disable_batch_insert =
      false;                  /**< Set if batch inserts should be disabled */
  bool try_reconnect = false; /**< Try to reconnect a database connection when
                         its dropped */
  bool exit_on_fatal = false; /**< Make any fatal error in the connection to the
                         database exit the program */
  uint32_t pooling_min_connections =
      0; /**< When using sql pooling start with this
        number of connections to the database */
  uint32_t pooling_max_connections = 0; /**< When using sql pooling maximum
                                       number of connections to the database */
  uint32_t pooling_increment_connections = 0; /**< When using sql pooling
                                             increment the pool with this amount
                                             when its to small */
  uint32_t pooling_idle_timeout =
      0; /**< When using sql pooling set this to the number
        of seconds to keep an idle connection */
  uint32_t pooling_validate_timeout = 0; /**< When using sql pooling set this to
                                        the number of seconds after a idle
                                        connection should be validated */

  /**< Methods */
  char* display(POOLMEM* dst); /**< Get catalog information */
};

/**
 * Forward referenced structures
 */
struct runtime_client_status_t;
struct RuntimeStorageStatus;
struct runtime_job_status_t;

/**
 * Client Resource
 */
class ClientResource
    : public BareosResource
    , public TlsResource {
 public:
  ClientResource() = default;
  virtual ~ClientResource() = default;

  uint32_t Protocol = 0;       /* Protocol to use to connect */
  uint32_t AuthType = 0;       /* Authentication Type to use for protocol */
  uint32_t ndmp_loglevel = 0;  /* NDMP Protocol specific loglevel to use */
  uint32_t ndmp_blocksize = 0; /* NDMP Protocol specific blocksize to use */
  uint32_t FDport = 0;         /* Where File daemon listens */
  uint64_t SoftQuota = 0;      /* Soft Quota permitted in bytes */
  uint64_t HardQuota = 0;      /* Maximum permitted quota in bytes */
  uint64_t GraceTime = 0;      /* Time remaining on gracetime */
  uint64_t QuotaLimit = 0;     /* The total softquota supplied if over grace */
  utime_t SoftQuotaGracePeriod = {0}; /* Grace time for softquota */
  utime_t FileRetention = {0};        /* File retention period in seconds */
  utime_t JobRetention = {0};         /* Job retention period in seconds */
  utime_t heartbeat_interval = {0};   /* Interval to send heartbeats */
  char* address = nullptr;            /* Hostname for remote access to Client */
  char* lanaddress =
      nullptr; /* Hostname for remote access to Client if behind NAT in LAN
                */
  char* username =
      nullptr; /* Username to use for authentication if protocol supports it */
  CatalogResource* catalog = nullptr; /* Catalog resource */
  int32_t MaxConcurrentJobs = 0;      /* Maximum concurrent jobs */
  bool passive = false;               /* Passive Client */
  bool conn_from_dir_to_fd = false;   /* Connect to Client */
  bool conn_from_fd_to_dir = false;   /* Allow incoming connections */
  bool enabled = false;               /* Set if client is enabled */
  bool AutoPrune = false;             /* Do automatic pruning? */
  bool StrictQuotas = false;          /* Enable strict quotas? */
  bool QuotaIncludeFailedJobs =
      false; /* Ignore failed jobs when calculating quota */
  bool ndmp_use_lmdb =
      false; /* NDMP Protocol specific use LMDB for the FHDB or not */
  int64_t max_bandwidth = 0;              /* Limit speed on this client */
  runtime_client_status_t* rcs = nullptr; /* Runtime Client Status */
  ClientConnectionHandshakeMode connection_successful_handshake_ =
      ClientConnectionHandshakeMode::kUndefined;
};

/**
 * Store Resource
 */
class StorageResource
    : public BareosResource
    , public TlsResource {
 public:
  StorageResource() = default;
  virtual ~StorageResource() = default;

  uint32_t Protocol = 0;      /* Protocol to use to connect */
  uint32_t AuthType = 0;      /* Authentication Type to use for protocol */
  uint32_t SDport = 0;        /* Port where Directors connect */
  uint32_t SDDport = 0;       /* Data port for File daemon */
  char* address = nullptr;    /* Hostname for remote access to Storage */
  char* lanaddress = nullptr; /* Hostname for remote access to Storage if behind
                       NAT in LAN */
  char* username =
      nullptr; /* Username to use for authentication if protocol supports it */
  char* media_type = nullptr; /**< Media Type provided by this Storage */
  char* ndmp_changer_device = nullptr; /**< If DIR controls storage directly
                                (NDMP_NATIVE) changer device used */
  alist* device = nullptr;           /**< Alternate devices for this Storage */
  int32_t MaxConcurrentJobs = 0;     /**< Maximum concurrent jobs */
  int32_t MaxConcurrentReadJobs = 0; /**< Maximum concurrent jobs reading */
  bool enabled = false;              /**< Set if device is enabled */
  bool autochanger = false;          /**< Set if autochanger */
  bool collectstats =
      false; /**< Set if statistics should be collected of this SD */
  bool AllowCompress = false; /**< Set if this Storage should allow jobs to
                         enable compression */
  int64_t StorageId = 0;      /**< Set from Storage DB record */
  int64_t max_bandwidth =
      0; /**< Limit speed on this storage daemon for replication */
  utime_t heartbeat_interval = {0}; /**< Interval to send heartbeats */
  utime_t cache_status_interval = {
      0}; /**< Interval to cache the vol_list in the runtime_storage_status */
  RuntimeStorageStatus* runtime_storage_status = nullptr;
  StorageResource* paired_storage = nullptr; /**< Paired storage configuration
                                      item for protocols like NDMP */

  /* Methods */
  char* dev_name() const;
};

inline char* StorageResource::dev_name() const
{
  DeviceResource* dev = (DeviceResource*)device->first();
  return dev->resource_name_;
}

/**
 * This is a sort of "unified" store that has both the
 * storage pointer and the text of where the pointer was
 * found.
 */
class UnifiedStorageResource : public BareosResource {
 public:
  StorageResource* store = nullptr;
  POOLMEM* store_source = nullptr;

  UnifiedStorageResource()
  {
    store = nullptr;
    store_source = GetPoolMemory(PM_MESSAGE);
    *store_source = 0;
  }
  ~UnifiedStorageResource() { destroy(); }

  void SetSource(const char* where);
  void destroy();
};

inline void UnifiedStorageResource::destroy()
{
  if (store_source) {
    FreePoolMemory(store_source);
    store_source = nullptr;
  }
}

inline void UnifiedStorageResource::SetSource(const char* where)
{
  if (!store_source) { store_source = GetPoolMemory(PM_MESSAGE); }
  PmStrcpy(store_source, where);
}

/**
 * Job Resource
 */
/* clang-format off */
class JobResource : public BareosResource {
 public:
  JobResource() = default;
  virtual ~JobResource() = default;

  uint32_t Protocol = 0;       /**< Protocol to use to connect */
  uint32_t JobType = 0;        /**< Job type (backup, verify, restore) */
  uint32_t JobLevel = 0;       /**< default backup/verify level */
  int32_t Priority = 0;        /**< Job priority */
  uint32_t RestoreJobId = 0;   /**< What -- JobId to restore */
  int32_t RescheduleTimes = 0; /**< Number of times to reschedule job */
  uint32_t replace = 0;        /**< How (overwrite, ..) */
  uint32_t selection_type = 0;

  char* RestoreWhere = nullptr;  /**< Where on disk to restore -- directory */
  char* RegexWhere = nullptr;    /**< RegexWhere option */
  char* strip_prefix = nullptr;  /**< Remove prefix from filename  */
  char* add_prefix = nullptr;    /**< add prefix to filename  */
  char* add_suffix = nullptr;    /**< add suffix to filename -- .old */
  char* backup_format = nullptr; /**< Format of backup to use for protocols supporting multiple backup formats */
  char* RestoreBootstrap = nullptr; /**< Bootstrap file */
  char* WriteBootstrap = nullptr;   /**< Where to write bootstrap Job updates */
  char* WriteVerifyList = nullptr;  /**< List of changed files */
  utime_t MaxRunTime = {0};         /**< Max run time in seconds */
  utime_t MaxWaitTime = {0};        /**< Max blocking time in seconds */
  utime_t FullMaxRunTime = {0};     /**< Max Full job run time */
  utime_t DiffMaxRunTime = {0};     /**< Max Differential job run time */
  utime_t IncMaxRunTime = {0};      /**< Max Incremental job run time */
  utime_t MaxStartDelay = {0};      /**< Max start delay in seconds */
  utime_t MaxRunSchedTime = {0}; /**< Max run time in seconds from Scheduled time*/
  utime_t RescheduleInterval = {0}; /**< Reschedule interval */
  utime_t MaxFullInterval = {0};    /**< Maximum time interval between Fulls */
  utime_t MaxVFullInterval = {0}; /**< Maximum time interval between Virtual Fulls */
  utime_t MaxDiffInterval = {0}; /**< Maximum time interval between Diffs */
  utime_t DuplicateJobProximity = {0}; /**< Permitted time between duplicicates */
  utime_t AlwaysIncrementalJobRetention = {0}; /**< Timeinterval where incrementals are not consolidated */
  utime_t AlwaysIncrementalMaxFullAge = {0};   /**< If Full Backup is older than this age
                                                *   the consolidation job will include also the full */
  utime_t RunOnIncomingConnectInterval = {0};
  int64_t spool_size = 0;    /**< Size of spool file for this job */
  int64_t max_bandwidth = 0; /**< Speed limit on this job */
  int64_t FileHistSize = 0; /**< Hint about the size of the expected File history */
  int32_t MaxConcurrentJobs = 0;   /**< Maximum concurrent jobs */
  int32_t MaxConcurrentCopies = 0; /**< Limit number of concurrent jobs one Copy Job spawns */
  int32_t AlwaysIncrementalKeepNumber = 0; /**< Number of incrementals that are always left and not consolidated */
  int32_t MaxFullConsolidations = 0;       /**< Number of consolidate jobs to be started that will include a full */

  MessagesResource* messages = nullptr; /**< How and where to send messages */
  ScheduleResource* schedule = nullptr; /**< When -- Automatic schedule */
  ClientResource* client = nullptr;     /**< Who to backup */
  FilesetResource* fileset = nullptr;   /**< What to backup -- Fileset */
  CatalogResource* catalog = nullptr;   /**< Which Catalog to use */
  alist* storage = nullptr; /**< Where is device -- list of Storage to be used */
  PoolResource* pool = nullptr;       /**< Where is media -- Media Pool */
  PoolResource* full_pool = nullptr;  /**< Pool for Full backups */
  PoolResource* vfull_pool = nullptr; /**< Pool for Virtual Full backups */
  PoolResource* inc_pool = nullptr;   /**< Pool for Incremental backups */
  PoolResource* diff_pool = nullptr;  /**< Pool for Differental backups */
  PoolResource* next_pool = nullptr; /**< Next Pool for Copy/Migration Jobs and Virtual backups */
  char* selection_pattern = nullptr;
  JobResource* verify_job = nullptr; /**< Job name to verify */
  JobResource* jobdefs = nullptr;    /**< Job defaults */
  alist* run_cmds = nullptr;         /**< Run commands */
  alist* RunScripts = nullptr; /**< Run {client} program {after|before} Job */
  alist* FdPluginOptions = nullptr; /**< Generic FD plugin options used by this Job */
  alist* SdPluginOptions = nullptr; /**< Generic SD plugin options used by this Job */
  alist* DirPluginOptions = nullptr;           /**< Generic DIR plugin options used by this Job */
  alist* base = nullptr; /**< Base jobs */

  bool allow_mixed_priority = false; /**< Allow jobs with higher priority concurrently with this */
  bool where_use_regexp = false;  /**< true if RestoreWhere is a BareosRegex */
  bool RescheduleOnError = false; /**< Set to reschedule on error */
  bool RescheduleIncompleteJobs = false; /**< Set to reschedule incomplete Jobs */
  bool PrefixLinks = false;         /**< Prefix soft links with Where path */
  bool PruneJobs = false;           /**< Force pruning of Jobs */
  bool PruneFiles = false;          /**< Force pruning of Files */
  bool PruneVolumes = false;        /**< Force pruning of Volumes */
  bool SpoolAttributes = false;     /**< Set to spool attributes in SD */
  bool spool_data = false;          /**< Set to spool data in SD */
  bool rerun_failed_levels = false; /**< Upgrade to rerun failed levels */
  bool PreferMountedVolumes = false; /**< Prefer vols mounted rather than new one */
  bool write_part_after_job = false; /**< Set to write part after job in SD */
  bool enabled = false;              /**< Set if job enabled */
  bool accurate = false;             /**< Set if it is an accurate backup job */
  bool AllowDuplicateJobs = false;   /**< Allow duplicate jobs */
  bool AllowHigherDuplicates = false; /**< Permit Higher Level */
  bool CancelLowerLevelDuplicates = false; /**< Cancel lower level backup jobs */
  bool CancelQueuedDuplicates = false;  /**< Cancel queued jobs */
  bool CancelRunningDuplicates = false; /**< Cancel Running jobs */
  bool PurgeMigrateJob = false;         /**< Purges source job on completion */
  bool IgnoreDuplicateJobChecking = false; /**< Ignore Duplicate Job Checking */
  bool SaveFileHist = false; /**< Ability to disable File history saving for certain protocols */
  bool AlwaysIncremental = false; /**< Always incremental with regular consolidation */

  runtime_job_status_t* rjs = nullptr; /**< Runtime Job Status */

  /* Methods */
  virtual bool Validate() override;
};
/* clang-format on */

#undef MAX_FOPTS
#define MAX_FOPTS 40

/**
 * File options structure
 */
struct FileOptions {
  FileOptions() = default;
  virtual ~FileOptions() = default;

  char opts[MAX_FOPTS] = {0}; /**< Options string */
  alist regex;                /**< Regex string(s) */
  alist regexdir;             /**< Regex string(s) for directories */
  alist regexfile;            /**< Regex string(s) for files */
  alist wild;                 /**< Wild card strings */
  alist wilddir;              /**< Wild card strings for directories */
  alist wildfile;             /**< Wild card strings for files */
  alist wildbase;             /**< Wild card strings for files without '/' */
  alist base;                 /**< List of base names */
  alist fstype;               /**< File system type limitation */
  alist Drivetype;            /**< Drive type limitation */
  alist meta;                 /**< Backup meta information */
  char* reader = nullptr;     /**< Reader program */
  char* writer = nullptr;     /**< Writer program */
  char* plugin = nullptr;     /**< Plugin program */
};

/**
 * This is either an include item or an exclude item
 */
class IncludeExcludeItem {
 public:
  IncludeExcludeItem() = default;
  virtual ~IncludeExcludeItem() = default;

  FileOptions* current_opts = nullptr;
  std::vector<FileOptions*> file_options_list;
  alist name_list;   /**< Filename list -- holds char * */
  alist plugin_list; /**< Filename list for plugins */
  alist ignoredir;   /**< Ignoredir string */
};

/**
 * FileSet Resource
 */
class FilesetResource : public BareosResource {
 public:
  FilesetResource() = default;
  virtual ~FilesetResource() = default;

  bool new_include = false; /**< Set if new include used */
  std::vector<IncludeExcludeItem*> include_items;
  std::vector<IncludeExcludeItem*> exclude_items;
  bool have_MD5 = false;          /**< Set if MD5 initialized */
  MD5_CTX md5c = {0};             /**< MD5 of include/exclude */
  char MD5[30]{0};                /**< Base 64 representation of MD5 */
  bool ignore_fs_changes = false; /**< Don't force Full if FS changed */
  bool enable_vss = false;        /**< Enable Volume Shadow Copy */

  /* Methods */
  bool PrintConfig(OutputFormatterResource& send,
                   const ConfigurationParser& my_config /* unused */,
                   bool hide_sensitive_data = false,
                   bool verbose = false) override;
  void PrintConfigIncludeExcludeOptions(OutputFormatterResource& send,
                                        FileOptions* fo,
                                        bool verbose);
  std::string GetOptionValue(const char** option);
};

/**
 * Schedule Resource
 */
class ScheduleResource : public BareosResource {
 public:
  ScheduleResource() = default;
  virtual ~ScheduleResource() = default;

  RunResource* run = nullptr;
  bool enabled = false; /* Set if schedule is enabled */
};

/**
 * Counter Resource
 */
class CounterResource : public BareosResource {
 public:
  CounterResource() = default;
  virtual ~CounterResource() = default;

  int32_t MinValue = 0;                   /* Minimum value */
  int32_t MaxValue = 0;                   /* Maximum value */
  int32_t CurrentValue = 0;               /* Current value */
  CounterResource* WrapCounter = nullptr; /* Wrap counter name */
  CatalogResource* Catalog = nullptr;     /* Where to store */
  bool created;                           /* Created in DB */
};

/**
 * Pool Resource
 */
class PoolResource : public BareosResource {
 public:
  PoolResource() = default;
  virtual ~PoolResource() = default;

  char* pool_type = nullptr;        /* Pool type */
  char* label_format = nullptr;     /* Label format string */
  char* cleaning_prefix = nullptr;  /* Cleaning label prefix */
  int32_t LabelType = 0;            /* Bareos/ANSI/IBM label type */
  uint32_t max_volumes = 0;         /* Max number of volumes */
  utime_t VolRetention = {0};       /* Volume retention period in seconds */
  utime_t VolUseDuration = {0};     /* Duration volume can be used */
  uint32_t MaxVolJobs = 0;          /* Maximum jobs on the Volume */
  uint32_t MaxVolFiles = 0;         /* Maximum files on the Volume */
  uint64_t MaxVolBytes = 0;         /* Maximum bytes on the Volume */
  utime_t MigrationTime = {0};      /* Time to migrate to next pool */
  uint64_t MigrationHighBytes = 0;  /* When migration starts */
  uint64_t MigrationLowBytes = 0;   /* When migration stops */
  PoolResource* NextPool = nullptr; /* Next pool for migration */
  alist* storage = nullptr; /* Where is device -- list of Storage to be used */
  bool use_catalog = false; /* Maintain catalog for media */
  bool catalog_files = false;          /* Maintain file entries in catalog */
  bool use_volume_once = false;        /* Write on volume only once */
  bool purge_oldest_volume = false;    /* Purge oldest volume */
  bool recycle_oldest_volume = false;  /* Attempt to recycle oldest volume */
  bool recycle_current_volume = false; /* Attempt recycle of current volume */
  bool AutoPrune = false;              /* Default for pool auto prune */
  bool Recycle = false;                /* Default for media recycle yes/no */
  uint32_t action_on_purge =
      0; /* Action on purge, e.g. truncate the disk volume */
  PoolResource* RecyclePool =
      nullptr; /* RecyclePool destination when media is purged */
  PoolResource* ScratchPool =
      nullptr; /* ScratchPool source when requesting media */
  CatalogResource* catalog = nullptr; /* Catalog to be used */
  utime_t FileRetention = {0};        /* File retention period in seconds */
  utime_t JobRetention = {0};         /* Job retention period in seconds */
  uint32_t MinBlocksize = 0;          /* Minimum Blocksize */
  uint32_t MaxBlocksize = 0;          /* Maximum Blocksize */
};

/**
 * Run structure contained in Schedule Resource
 */
class RunResource : public BareosResource {
 public:
  RunResource() = default;
  virtual ~RunResource() = default;

  RunResource* next = nullptr; /**< points to next run record */
  uint32_t level = 0;          /**< level override */
  int32_t Priority = 0;        /**< priority override */
  uint32_t job_type = 0;
  utime_t MaxRunSchedTime = {0};    /**< max run time in sec from Sched time */
  bool MaxRunSchedTime_set = false; /**< MaxRunSchedTime given */
  bool spool_data = false;          /**< Data spooling override */
  bool spool_data_set = false;      /**< Data spooling override given */
  bool accurate = false;            /**< accurate */
  bool accurate_set = false;        /**< accurate given */

  PoolResource* pool = nullptr;       /**< Pool override */
  PoolResource* full_pool = nullptr;  /**< Full Pool override */
  PoolResource* vfull_pool = nullptr; /**< Virtual Full Pool override */
  PoolResource* inc_pool = nullptr;   /**< Incr Pool override */
  PoolResource* diff_pool = nullptr;  /**< Diff Pool override */
  PoolResource* next_pool = nullptr;  /**< Next Pool override */
  StorageResource* storage = nullptr; /**< Storage override */
  MessagesResource* msgs = nullptr;   /**< Messages override */
  uint32_t minute = 0;                /* minute to run job */
  time_t scheduled_last = {0};
  DateTimeBitfield date_time_bitfield;
};

ConfigurationParser* InitDirConfig(const char* configfile, int exit_code);
bool PropagateJobdefs(int res_type, JobResource* res);
bool ValidateResource(int type, ResourceItem* items, BareosResource* res);

bool print_datatype_schema_json(PoolMem& buffer,
                                int level,
                                const int type,
                                ResourceItem items[],
                                const bool last = false);
#ifdef HAVE_JANSSON
json_t* json_datatype(const int type, ResourceItem items[]);
#endif
const char* AuthenticationProtocolTypeToString(uint32_t auth_protocol);
const char* JobLevelToString(int level);
extern "C" char* job_code_callback_director(JobControlRecord* jcr, const char*);
const char* GetUsageStringForConsoleConfigureCommand();
void DestroyConfigureUsageString();
bool PopulateDefs();
std::vector<JobResource*> GetAllJobResourcesByClientName(std::string name);

} /* namespace directordaemon */
#endif  // BAREOS_DIRD_DIRD_CONF_H_
